# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Meta-target to enable all checks with runtime library.
add_library(iotsdk-sanitizers-ubsan INTERFACE EXCLUDE_FROM_ALL)
target_sources(iotsdk-sanitizers-ubsan
    INTERFACE
        ${CMAKE_CURRENT_SOURCE_DIR}/ubsan.c
)

# Minimal runtime is clang-only.
if(CMAKE_C_COMPILER_ID STREQUAL "ARMClang")
    target_compile_options(iotsdk-sanitizers-ubsan
        INTERFACE
            -fsanitize-minimal-runtime
    )
endif()

target_include_directories(iotsdk-sanitizers-ubsan
    INTERFACE
        ${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(iotsdk-sanitizers-ubsan
    INTERFACE
        iotsdk-sanitizers-common
)

# Meta-target to enable all checks without runtime library.
add_library(iotsdk-sanitizers-ubsan-no-rt INTERFACE EXCLUDE_FROM_ALL)
target_link_libraries(iotsdk-sanitizers-ubsan-no-rt
    INTERFACE
        iotsdk-sanitizers-common
)

# Create a library for CHECK and link the no-RT meta target to it.
function(iotsdk_ubsan_create_library_no_rt CHECK)
add_library(iotsdk-sanitizers-ubsan-${CHECK} INTERFACE EXCLUDE_FROM_ALL)
    target_compile_options(iotsdk-sanitizers-ubsan-${CHECK}
        INTERFACE
            -fsanitize=${CHECK}
    )

    target_link_libraries(iotsdk-sanitizers-ubsan-no-rt
        INTERFACE
            iotsdk-sanitizers-ubsan-${CHECK}
    )
endfunction()

# Create a library for CHECK and link the RT and no-RT meta targets to it.
function(iotsdk_ubsan_create_library_with_rt CHECK)
    iotsdk_ubsan_create_library_no_rt(${CHECK})

    target_link_libraries(iotsdk-sanitizers-ubsan
        INTERFACE
            iotsdk-sanitizers-ubsan-${CHECK}
    )
endfunction()

# Checks which support RT.
iotsdk_ubsan_create_library_with_rt(alignment)
iotsdk_ubsan_create_library_with_rt(bool)
iotsdk_ubsan_create_library_with_rt(builtin)
iotsdk_ubsan_create_library_with_rt(bounds)
iotsdk_ubsan_create_library_with_rt(enum)
iotsdk_ubsan_create_library_with_rt(float-cast-overflow)
iotsdk_ubsan_create_library_with_rt(float-divide-by-zero)
iotsdk_ubsan_create_library_with_rt(integer-divide-by-zero)
iotsdk_ubsan_create_library_with_rt(nonnull-attribute)
iotsdk_ubsan_create_library_with_rt(null)
iotsdk_ubsan_create_library_with_rt(object-size)
iotsdk_ubsan_create_library_with_rt(pointer-overflow)
iotsdk_ubsan_create_library_with_rt(return)
iotsdk_ubsan_create_library_with_rt(returns-nonnull-attribute)
iotsdk_ubsan_create_library_with_rt(shift)
iotsdk_ubsan_create_library_with_rt(signed-integer-overflow)
iotsdk_ubsan_create_library_with_rt(unreachable)
iotsdk_ubsan_create_library_with_rt(vla-bound)

# Clang-only checks.
if(CMAKE_C_COMPILER_ID STREQUAL "ARMClang")
    iotsdk_ubsan_create_library_with_rt(implicit-unsigned-integer-truncation)
    iotsdk_ubsan_create_library_with_rt(implicit-signed-integer-truncation)
    iotsdk_ubsan_create_library_with_rt(implicit-integer-sign-change)
    iotsdk_ubsan_create_library_with_rt(nullability-arg)
    iotsdk_ubsan_create_library_with_rt(nullability-assign)
    iotsdk_ubsan_create_library_with_rt(nullability-return)
    iotsdk_ubsan_create_library_with_rt(unsigned-shift-base)
    iotsdk_ubsan_create_library_with_rt(unsigned-integer-overflow)
endif()

# Checks which do not support RT.
iotsdk_ubsan_create_library_no_rt(function)
iotsdk_ubsan_create_library_no_rt(objc-cast)
iotsdk_ubsan_create_library_no_rt(vptr)
